home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / game / shoot / ADescentSrc.lha / descent / Amiga / amiga_serial.c < prev    next >
C/C++ Source or Header  |  1998-07-14  |  19KB  |  683 lines

  1. /*
  2. ** Amiga_Serial
  3. ** Amiga serial i/o stuff
  4. **
  5. ** $Id: amiga_serial.c,v 1.5 1998/07/14 20:59:02 nobody Exp $
  6. ** $Revision: 1.5 $
  7. ** $Author: nobody $
  8. ** $Date: 1998/07/14 20:59:02 $
  9. */
  10.  
  11. #include <stdio.h>
  12. #include <utility/tagitem.h>
  13. #include <exec/exec.h>
  14. #include <proto/exec.h>
  15. #include <proto/utility.h>
  16. #include <devices/serial.h>
  17. #include "amiga_serial.h"
  18.  
  19. #include "types.h"
  20. #include "newmenu.h"
  21. #include "args.h"
  22. #include "multi.h"
  23.  
  24. struct MsgPort *SerialMP,   *SerialMPWrite;
  25. struct IOExtSer *SerialIO,  *SerialIOWrite;
  26. short amiserial_write_IO = 0;                      //  Which IORequest to use
  27.  
  28. #define SEIO struct IOExtSer *
  29. #define STIO struct IORequest *
  30.  
  31. #define MAXSERIAL   128
  32. #define SERFLAGS    (SERF_7WIRE | SERF_RAD_BOOGIE | SERF_XDISABLED)
  33.  
  34. #define db_printf(a) /* printf a */
  35.  
  36. int amiserial_unit;
  37. char amiserial_device[MAXSERIAL];
  38. int amiserial_up=0;
  39. UBYTE amiserial_busy_write = 0;
  40.  
  41. extern int Inferno_verbose;
  42. extern int com_speed;
  43. extern int com_open;
  44.  
  45. UBYTE sendbuffer[512];
  46.  
  47. #define RCVBUFSIZE 4096
  48. UBYTE ReceiveBuffer[RCVBUFSIZE];
  49. int BufferPos=0;
  50. int BufferFill=0;
  51.  
  52. #define CARRIER_SIGNAL (1<<5)
  53.  
  54. void amiserial_do(struct IOExtSer *io, ULONG command)
  55. {
  56.     io->IOSer.io_Command = command;
  57.     DoIO((STIO)io);
  58. }
  59.  
  60. void amiserial_close(void)
  61. // shut down serial port
  62. {
  63.     if (!amiserial_up)
  64.         return;
  65.     if (!CheckIO((STIO)SerialIO)) {
  66.         AbortIO((STIO)SerialIO);
  67.         WaitIO((STIO)SerialIO);
  68.     }
  69.     if (!CheckIO((STIO)SerialIOWrite)) {
  70.         AbortIO((STIO)SerialIOWrite);
  71.         WaitIO((STIO)SerialIOWrite);
  72.     }
  73.     CloseDevice((STIO)SerialIO);
  74.  
  75.     DeleteExtIO((STIO)SerialIO);
  76.     DeleteExtIO((STIO)SerialIOWrite);
  77.  
  78.     DeleteMsgPort(SerialMP);
  79.     DeleteMsgPort(SerialMPWrite);
  80.     amiserial_up=0;
  81.  
  82.     if (Inferno_verbose) printf("Init_serial: Serial communication subsystem shut down\n");
  83.  
  84.     return;
  85. }
  86.  
  87. int amiserial_init(void)
  88. // Initialize the serial port
  89. {
  90.     int i;
  91.     int ioerr;
  92.  
  93.     if (amiserial_up)
  94.         return 0;
  95.  
  96.     atexit(amiserial_close);
  97.  
  98.     if (Inferno_verbose) printf("Init_serial: Attempting to initialize serial hardware\n");
  99.  
  100.     i=FindArg("-serialname");
  101.     if (i) strncpy(amiserial_device, Args[i+1], MAXSERIAL);
  102.     else   strcpy (amiserial_device, "serial.device");
  103.  
  104.  
  105.     i=FindArg("-serialunit");
  106.     if (i) amiserial_unit = atoi(Args[i+1]);
  107.     else   amiserial_unit = 0;
  108.  
  109.     if (Inferno_verbose) printf("Init_serial: Serial device name %s, unit %d\n", amiserial_device, amiserial_unit);
  110.  
  111.     SerialMP = CreateMsgPort();
  112.     if (!SerialMP) return -1;
  113.  
  114.     SerialMPWrite = CreateMsgPort();
  115.     if (!SerialMPWrite) goto cleanup;
  116.  
  117.     if (Inferno_verbose) printf("Init_serial: Created serial message port\n");
  118.  
  119.     SerialIO = (SEIO)CreateExtIO(SerialMP, sizeof(struct IOExtSer));
  120.     if (!SerialIO) goto cleanup;
  121.  
  122.     SerialIOWrite = (SEIO)CreateExtIO(SerialMPWrite, sizeof(struct IOExtSer));
  123.     if (!SerialIOWrite) goto cleanup;
  124.  
  125.     if (Inferno_verbose) printf("Init_serial: Created IOExtSer for Read and Write\n");
  126.  
  127.     SerialIO->io_SerFlags = SERFLAGS;
  128.     SerialIO->io_SerFlags &= ~SERF_PARTY_ON;
  129.  
  130.     ioerr = OpenDevice(amiserial_device, 0L, (STIO)SerialIO, 0);
  131.     if (ioerr) goto cleanup;
  132.  
  133.     memcpy(SerialIOWrite, SerialIO, sizeof(struct IOExtSer));
  134.     SerialIOWrite->IOSer.io_Message.mn_ReplyPort = SerialMPWrite;
  135.     SerialIOWrite->IOSer.io_Message.mn_Node.ln_Type = 0;
  136.  
  137.     // Make sure those two babies have been used
  138.     amiserial_do(SerialIO,         CMD_CLEAR);
  139.     amiserial_do(SerialIOWrite,    CMD_CLEAR);
  140.  
  141.     if (Inferno_verbose) printf("Init_serial: Successful\n");
  142.  
  143.     amiserial_up = 1;
  144.     return 0;
  145.  
  146. cleanup:
  147.     if (SerialIO)           DeleteExtIO((STIO)SerialIO);
  148.     if (SerialIOWrite)      DeleteExtIO((STIO)SerialIOWrite);
  149.     if (SerialMP)           DeleteMsgPort(SerialMP);
  150.     if (SerialMPWrite)      DeleteMsgPort(SerialMPWrite);
  151.     return -1;
  152. }
  153.  
  154. int amiserial_chars(void)
  155. // Query the number of pending characters at the serial port for reading
  156. {
  157.     SerialIO->IOSer.io_Command = SDCMD_QUERY;
  158.     SerialIO->IOSer.io_Actual  = 0;
  159.     DoIO((STIO)SerialIO); // used to be SendIO
  160.     return (int)(SerialIO->IOSer.io_Actual);
  161. }
  162.  
  163. int amiserial_read(char *where, int chars)
  164. {
  165.     SerialIO->IOSer.io_Data     = (APTR)where;
  166.     SerialIO->IOSer.io_Length   = chars;
  167.     amiserial_do(SerialIO, CMD_READ);
  168.     return SerialIO->IOSer.io_Actual;
  169. }
  170.  
  171. void amiserial_flush(void)
  172. {
  173.     SerialIO->IOSer.io_Command = CMD_CLEAR;
  174.     DoIO((STIO)SerialIO);
  175.     return;
  176. }
  177.  
  178. PORT * PortOpenGreenleafFast(int port, int baud,char parity,int databits, int stopbits)
  179. // Used by Descent to open a port
  180. // We use it to set serial parameters (port is opened at the start
  181. // by amiserial_init
  182. {
  183.     PORT *n;
  184.  
  185.     if (Inferno_verbose)
  186.         db_printf(("serial_open_port: Port %d (ignored), baud %d, format %1d %c %1d\n",
  187.             port, baud, databits, parity, stopbits));
  188.  
  189.     db_printf(("serial_open_port: bufsizes (%d, %d)\n", SerialIO->io_RBufLen,
  190.                 SerialIOWrite->io_RBufLen));
  191.  
  192.     n=(PORT *)malloc(sizeof(PORT));
  193.     if (n) {
  194.         n->status=0;
  195.         SerialIO->io_Baud       = (ULONG)baud;
  196.         SerialIO->io_ReadLen    = (UBYTE)databits;
  197.         SerialIO->io_WriteLen   = (UBYTE)databits;
  198.         SerialIO->io_StopBits   = (UBYTE)stopbits;
  199.         SerialIO->IOSer.io_Command = SDCMD_SETPARAMS;
  200.         if (Inferno_verbose) printf("serial_open_port: Setting serial device parameters for read\n");
  201.         DoIO((STIO)SerialIO);
  202.         SerialIOWrite->io_Baud       = (ULONG)baud;
  203.         SerialIOWrite->io_ReadLen    = (UBYTE)databits;
  204.         SerialIOWrite->io_WriteLen   = (UBYTE)databits;
  205.         SerialIOWrite->io_StopBits   = (UBYTE)stopbits;
  206.         SerialIOWrite->IOSer.io_Command = SDCMD_SETPARAMS;
  207.         if (Inferno_verbose) printf("serial_open_port: Setting serial device parameters for write\n");
  208.         DoIO((STIO)SerialIOWrite);
  209.  
  210.         if (Inferno_verbose) printf("serial_open_port: Done\n");
  211.     }
  212.     return n;
  213. }
  214.  
  215. void SetDtr(PORT *port,int state) // not used
  216. {
  217.     return;
  218. }
  219.  
  220. void SetRts(PORT *port,int state) // not used
  221. {
  222.     return;
  223. }
  224.  
  225. void UseRtsCts(PORT *port,int state) // 7WIRE handshake by default
  226. {
  227.     return;
  228. }
  229.  
  230. void WriteChar(PORT *port,char ch)
  231. // Write one character to the serial port. First argument is ignored
  232. // since Descent only uses one port
  233. {
  234.     SerialIOWrite->IOSer.io_Length = 1;
  235.     SerialIOWrite->IOSer.io_Data = (APTR)&ch;
  236.     SerialIOWrite->IOSer.io_Command = CMD_WRITE;
  237.     DoIO((STIO)SerialIOWrite);
  238. }
  239.  
  240. void ClearRXBuffer(PORT *port) // Not uesd
  241. {
  242.     return;
  243. }
  244.  
  245. void ReadBufferTimed(PORT *port, char *buf,int a, int b) // not used
  246. {
  247.     return;
  248. }
  249.  
  250. int Change8259Priority(int a) // just flags success
  251. {
  252.     return ASSUCCESS;
  253. }
  254.  
  255. int FastSetPortHardware(PORT *port,int IRQ, int baseaddr) // just flags success
  256. {
  257.     return ASSUCCESS;
  258. }
  259.  
  260. void FastSet16550TriggerLevel(int a)
  261. {
  262.     return;
  263. }
  264.  
  265. void FastSet16550UseTXFifos(int a)
  266. {
  267.     return;
  268. }
  269.  
  270.  
  271. void FastSavePortParameters(PORT *port)
  272. {
  273.     return;
  274. }
  275.  
  276. int PortClose(PORT *port) // port automatically deallocated by amiserial_close
  277. {
  278.     return ASSUCCESS;
  279. }
  280.  
  281. void FastRestorePortParameters(int num)
  282. {
  283.     return;
  284. }
  285.  
  286. int GetCd(PORT *port)
  287. // Query the status of the CARRIER DETECT signal
  288. {
  289.     UWORD Serial_Status;
  290.  
  291.     SerialIO->IOSer.io_Command = SDCMD_QUERY;
  292.     SendIO((STIO)SerialIO);
  293.  
  294.     Serial_Status = SerialIO->io_Status;
  295.     if (Serial_Status & CARRIER_SIGNAL) return 0;   // CD is low-active
  296.     else return 1;
  297. }
  298.  
  299. int ReadCharTimed(PORT *port, int blah) // Only used to flush the device...
  300. {
  301.     SerialIO->IOSer.io_Command = CMD_CLEAR;
  302.     DoIO((STIO)SerialIO);
  303.     return -1; // returns -1 (no more characters)
  304. }
  305.  
  306. int old_ReadChar(PORT *port)
  307. // Read a character from the serial port
  308. // returns -1 if the port is empty.
  309. {
  310.     int chars;
  311.     unsigned char buffer[20];
  312.     int ret;
  313.  
  314.     buffer[0]=0;
  315.     chars=amiserial_chars();
  316.     db_printf(("amiga_serial: ReadChar has %d character pending\n", chars));
  317.     if (chars) {    // There are pending characters
  318.         SerialIO->IOSer.io_Command = CMD_READ;
  319.         SerialIO->IOSer.io_Data = (APTR)buffer;
  320.         SerialIO->IOSer.io_Length = 1;
  321.         db_printf(("amiga_serial: ReadChar reads one charachter\n"));
  322.         DoIO((STIO)SerialIO);
  323.         db_printf(("amiga_serial: ReadChar has read %u\n", (unsigned int)buffer[0]));
  324.         ret = (int)buffer[0];
  325.         if (ret<0) ret=-ret;
  326.         return ret;
  327.     } else {        // No characters available
  328.         return ASBUFREMPTY;
  329.     }
  330. }
  331.  
  332. int ReadChar(PORT *port)
  333. {
  334.     int ret;
  335.     int chars;
  336.     if (BufferPos<=BufferFill && BufferFill!=0) {
  337.         ret = (int)ReceiveBuffer[BufferPos++];
  338.         if (ret<0) ret=-ret;
  339.         return ret;
  340.     } else {
  341.         chars = amiserial_chars();
  342.         if (!chars) return ASBUFREMPTY;
  343.         if (chars>RCVBUFSIZE) chars = RCVBUFSIZE;
  344.         SerialIO->IOSer.io_Command = CMD_READ;
  345.         SerialIO->IOSer.io_Data    = (APTR)ReceiveBuffer;
  346.         SerialIO->IOSer.io_Length  = (ULONG)chars;
  347.         SerialIO->IOSer.io_Flags  |= IOF_QUICK;
  348.         DoIO((STIO)SerialIO);
  349.         BufferFill = (int)(SerialIO->IOSer.io_Actual)-1;
  350.         BufferPos = 0;
  351.         ret = (int)ReceiveBuffer[BufferPos++];
  352.         if (ret<0) ret=-ret;
  353.         return ret;
  354.     }
  355. }
  356.  
  357.  
  358. void ClearLineStatus(PORT *port)
  359. {
  360.     return;
  361. }
  362. int HMInputLine(PORT *port, int a, char *buf, int b)    // stuff below only used by modem stuff
  363. {
  364.     return 0;
  365. }
  366. void HMWaitForOK(int a, int b)
  367. {
  368.     return;
  369. }
  370. HMSendString(PORT *port, char *msg)
  371. {
  372.     return;
  373. }
  374. void HMReset(PORT *port)
  375. {   
  376.     return;
  377. }
  378. void HMDial(PORT *port, char *pPhoneNum)
  379. {
  380.     return;
  381. }
  382. void HMSendStringNoWait(PORT *port, char *pbuf,int a)
  383. {
  384.     return;
  385. }
  386. void HMAnswer(PORT *port)
  387. {
  388.     return;
  389. }
  390. void ClearTXBuffer(PORT *port) // Not used
  391. {
  392.     return;
  393. }
  394. void WriteBuffer(PORT *port, char *pbuff, int len) // Not used
  395. {
  396.     return;
  397. }
  398.  
  399. #define EOR_MARK 0xaa
  400.  
  401. #if 0
  402. void com_send_ptr(char *ptr, int len)
  403. {
  404.     int i=0;
  405.     BYTE error;
  406.     ULONG WaitMask = SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|1<<(SerialMPWrite->mp_SigBit);
  407.     ULONG GotSig;
  408.  
  409.     db_printf(("com_send_ptr_amiga: sending %d characters, packet type %d\n", len, *ptr));
  410.  
  411.     while (len) {
  412.         sendbuffer[i] = (UBYTE)*ptr++;
  413.         if (sendbuffer[i]==EOR_MARK) {
  414.             i++;
  415.             sendbuffer[i]=EOR_MARK;
  416.         }
  417.         i++;
  418.         len--;
  419.     }
  420.     sendbuffer[i++]=EOR_MARK;
  421.     sendbuffer[i++] = 0;
  422.     db_printf(("com_send_ptr_amiga: prepared package for sending\n"));
  423.     if (CheckIO((STIO)SerialIOWrite) == NULL) {
  424.         error=WaitIO((STIO)SerialIOWrite);
  425.         if (error) printf("com_send_ptr_amiga: Error %d during WaitIO()\n", error);
  426.     }
  427.     db_printf(("com_send_ptr_amiga: sending package\n"));
  428.     SerialIOWrite->IOSer.io_Data    = (APTR)sendbuffer;
  429.     SerialIOWrite->IOSer.io_Length  = (ULONG)i;
  430.     SerialIOWrite->IOSer.io_Command = CMD_WRITE;
  431.     SerialIOWrite->IOSer.io_Flags |= IOF_QUICK;
  432.     SendIO((STIO)SerialIOWrite);
  433. /*    db_printf(("com_send_ptr_amiga: Going to sleep\n"));
  434.     while (1) {
  435.         GotSig = Wait(WaitMask);
  436.         db_printf(("com_send_ptr_amiga: Yawn\n"));
  437.         if (SIGBREAKF_CTRL_D & GotSig) break;               //  ^D to kick it`s ass
  438.         if (SIGBREAKF_CTRL_C & GotSig) exit(1);             //  ^C to kill it
  439.         if (CheckIO(SerialIOWrite)) {
  440.             WaitIO(SerialIOWrite);
  441.             break;
  442.         }
  443.     }*/
  444.  
  445.     db_printf(("com_send_ptr_amiga: package send ioError code %d\n",
  446.         SerialIOWrite->IOSer.io_Error));
  447. }
  448. #endif
  449.  
  450. /*
  451.  * com_send_ptr second generation
  452.  ***************************************************************************
  453.  *
  454.  * The package to send is wrapped into a "superpackage" of the following layout:
  455.  * 'PACK'       4 byte header
  456.  * len          ULONG length of package
  457.  * <data>       len bytes of data
  458.  *
  459.  * EOR_MARKS are not doubled, and are not used
  460.  *
  461.  * Caveats: No longer compatible with PC serial stuff
  462.  *          Slightly more overhead due to header
  463.  *
  464.  * PLUS:    Might work.
  465.  *          More efficient because of full package send.
  466.  *
  467.  */
  468. void com_send_ptr(char *ptr, int len)
  469. {
  470.     ULONG packlen = (ULONG)len;
  471.  
  472.     db_printf(("amiserial_com_send_ptr: about to send package length %d type %u\n", len, (unsigned int)*ptr));
  473.     sendbuffer[0] = 'P';                    // Write header
  474.     sendbuffer[1] = 'A';
  475.     sendbuffer[2] = 'C';
  476.     sendbuffer[3] = 'K';
  477.     *(ULONG *)(&sendbuffer[4]) = packlen;   // Write length
  478.     memcpy(&sendbuffer[8], ptr, len);       // Copy bytes into send buffer
  479.  
  480.     db_printf(("amiserial_com_send_ptr: Package prepared, verifying accessability\n"));
  481.  
  482.     if (amiserial_busy_write) {
  483.         db_printf(("amiserial_com_send_ptr: Wait for receive device\n"));
  484.         if (!(CheckIO((STIO)SerialIO))) {   //  Check if we need to receive first
  485.             WaitIO((STIO)SerialIO);
  486.         }
  487.         db_printf(("amiserial_com_send_ptr: Wait for send device\n"));
  488.         WaitIO((STIO)SerialIOWrite);
  489.         amiserial_busy_write = 0;
  490.     }
  491.  
  492.     db_printf(("amiserial_com_send_ptr: Sending data...\n"));
  493.  
  494.     SerialIOWrite->IOSer.io_Data    = (APTR)sendbuffer;
  495.     SerialIOWrite->IOSer.io_Length  = (ULONG)len+8;
  496.     SerialIOWrite->IOSer.io_Command = CMD_WRITE;
  497.     SerialIOWrite->IOSer.io_Flags |= IOF_QUICK;
  498. //    SendIO((STIO)SerialIOWrite);
  499.     DoIO((STIO)SerialIOWrite);
  500.  
  501. //    amiserial_busy_write = 1;
  502.     db_printf(("amiserial_com_send_ptr: After-send error codes are %d on %d\n",
  503.             SerialIOWrite->IOSer.io_Error, amiserial_write_IO));
  504.  
  505. //    amiserial_write_IO = (amiserial_write_IO+1)%2;
  506. }
  507.  
  508. /*
  509.  * com_receive_ptr
  510.  ***************************************************************************
  511.  *
  512.  * Try to receive a package from the serial interface
  513.  * ptr points to the receive buffer
  514.  *
  515.  *
  516.  * RETURNS:
  517.  *      -1 to indicate that no character was available
  518.  *      -2 to indicate full message read
  519.  *       0 to indicate partial message read (currently never)
  520.  *
  521.  *      len is set to the number of characters read, i.e. the package length
  522.  */
  523. int com_receive_ptr(char *ptr, int *len)
  524. {
  525.     ULONG packhdr = 'P'<<24 | 'A'<<16 | 'C'<<8 | 'K';
  526.     int chars, rchars;
  527.     ULONG buffer[3];
  528.     static int amiserial_sync = 0;
  529.     ULONG length;
  530.     UBYTE c;
  531.  
  532.     db_printf(("com_receive_ptr: Trying to get package\n"));
  533.  
  534.     *len=0;
  535.     if (amiserial_sync != 0) {                  // Try to find the next package header
  536.         db_printf(("com_receive_prt: Trying sync\n"));
  537.         //  To resync, we search for the sequence PACK.
  538.         //  We do this letter by letter, until we`ve found them all in sequence.
  539.         //  In other words, this implements a finite state machine.
  540.         while (amiserial_sync != 0) {
  541.             if (amiserial_chars()==0) return -1;
  542.             SerialIO->IOSer.io_Command = CMD_READ;          //  Read one character
  543.             SerialIO->IOSer.io_Data    = (ULONG *)buffer;
  544.             SerialIO->IOSer.io_Length  = 1;
  545.             SerialIO->IOSer.io_Flags  |= IOF_QUICK;
  546.             DoIO((STIO)SerialIO);
  547.             c = (char)((char *)buffer)[0];
  548.             switch (amiserial_sync) {                       //  Try to find out which it must be
  549.                 case 1:
  550.                     if (c == 'P') {
  551.                         amiserial_sync++;                   //  It`s a P, so advance
  552.                         db_printf(("com_receive_prt: Sync 'P' -> %d\n",amiserial_sync));
  553.                     } else {
  554.                         amiserial_sync = 1;              //  No P, start over again
  555.                         return -1;
  556.                     }
  557.                     break;
  558.                 case 2:
  559.                     if (c == 'A') {
  560.                         amiserial_sync++;                   //  It`s a A, go on
  561.                         db_printf(("com_receive_prt: Sync 'A' -> %d\n",amiserial_sync));
  562.                     } else {
  563.                         amiserial_sync = 1;              //  No A, we start again at P
  564.                         return -1;
  565.                     }
  566.                     break;
  567.                 case 3:
  568.                     if (c == 'C') {
  569.                         amiserial_sync++;                   //  A 'C'
  570.                         db_printf(("com_receive_prt: Sync 'C' -> %d\n",amiserial_sync));
  571.                     } else {
  572.                         amiserial_sync = 1;
  573.                         return -1;
  574.                     }
  575.                     break;
  576.                 case 4:
  577.                     if (c == 'K') {
  578.                         amiserial_sync++;                   //  A 'K'
  579.                         db_printf(("com_receive_prt: Sync 'K' -> %d\n",amiserial_sync));
  580.                     } else {
  581.                         amiserial_sync = 1;
  582.                         return -1;
  583.                     }
  584.                     break;
  585.                 default:                                    //  Shouldn`t need this, but just in case
  586.                     amiserial_sync = 1;
  587.                     break;
  588.             }
  589.             //  We now check amiserial_sync for a 5. If we have one, all of the above came in
  590.             //  Sequence, and we can continue to read the length of the package.
  591.             //  Otherwise, we do it over again (We have no other choice. Possible future
  592.             //  extension: count how many times we looped, and break if it exceeds a given threshold.
  593.             if (amiserial_sync == 5) {                      //  got a valid PACK header
  594.                 if (amiserial_chars() < 4) return -1;       //  return an empty-buffer-mark if too few chars.
  595.                 db_printf(("com_receive_prt: sync'ed'\n"));
  596.                 SerialIO->IOSer.io_Command = CMD_READ;      //  Read the package length
  597.                 SerialIO->IOSer.io_Data    = (ULONG *)&length;
  598.                 SerialIO->IOSer.io_Length  = 4;
  599.                 SerialIO->IOSer.io_Flags  |= IOF_QUICK;
  600.                 db_printf(("com_receive_prt: reading length\n"));
  601.                 DoIO((STIO)SerialIO);
  602.                 amiserial_sync = 0;                         //  Stop resync
  603.                 *len = amiserial_read(ptr, length);         //  Read the package
  604.                 db_printf(("com_receive_ptr: Received %d characters resynced (expected %d)\n", *len, length));
  605.                 return -2;                                  //  Tell the caller we`ve got a package for him
  606.             }
  607.         }
  608.         return -1;
  609.     }
  610.  
  611.     chars = amiserial_chars();
  612.     db_printf(("com_receive_ptr: %d characters available\n", chars));
  613.     if (chars<8)
  614.         return -1;                               // 8 is minumum package length
  615.  
  616.     rchars = amiserial_read((char *)buffer, 8); // Read Package header and length
  617.                                                 // Should really check this return value
  618.     db_printf(("com_receive_ptr: Got %d characters\n", rchars));
  619.     if (buffer[0] != packhdr) {                 // Difficult case: invalid message
  620.         db_printf(("com_receive_ptr: Error - package header not found\n"));
  621.         amiserial_sync = 1;
  622.         return -1;                              // Say that the buffer was empty
  623.     }
  624.  
  625.     *len = amiserial_read(ptr, buffer[1]);      // Read the message
  626.     db_printf(("com_receive_ptr: Received %d characters (expected %d)\n", *len, buffer[1]));
  627.     return -2;                                  // Indicate full message has been read
  628. }
  629.  
  630. void com_param_setup(void) {
  631.  
  632.     newmenu_item m[10];
  633.     int choice = 0;
  634.     int num_options = 0;
  635.     char text[256];
  636.     int i;
  637.     int was_on = 0;
  638.  
  639.     sprintf(text, "%d", com_speed);
  640.  
  641.     if (com_open) {
  642.         was_on = 1;
  643.         com_disable();
  644.     }
  645.  
  646.     db_printf(("com_param_setup: Baud rate is %s\n", text));
  647.  
  648. /*    do { */
  649.         m[0].type       = NM_TYPE_TEXT;
  650.         m[0].text       = "Baud rate:";
  651.         m[1].type       = NM_TYPE_INPUT;
  652.         m[1].text_len   = 60;
  653.         m[1].text       = text;
  654.  
  655.         i = newmenu_do1( NULL, "Serial port options", 2, m, NULL, i);
  656.  
  657. /*    while (i > -1); */
  658.  
  659.     com_speed = atoi(text);
  660.  
  661.     if (was_on)
  662.         com_enable();
  663.  
  664.     SerialIO->io_Baud       = (ULONG)com_speed;
  665.     SerialIO->io_ReadLen    = (UBYTE)8;
  666.     SerialIO->io_WriteLen   = (UBYTE)8;
  667.     SerialIO->io_StopBits   = (UBYTE)1;
  668.     SerialIO->IOSer.io_Command = SDCMD_SETPARAMS;
  669.     if (Inferno_verbose) printf("com_param_setup: Setting serial device parameters for read: %d\n", com_speed);
  670.     DoIO((STIO)SerialIO);
  671.     SerialIOWrite->io_Baud       = (ULONG)com_speed;
  672.     SerialIOWrite->io_ReadLen    = (UBYTE)8;
  673.     SerialIOWrite->io_WriteLen   = (UBYTE)8;
  674.     SerialIOWrite->io_StopBits   = (UBYTE)1;
  675.     SerialIOWrite->IOSer.io_Command = SDCMD_SETPARAMS;
  676.     if (Inferno_verbose) printf("com_param_setup: Setting serial device parameters for write: %d\n", com_speed);
  677.     DoIO((STIO)SerialIOWrite);
  678.  
  679.     db_printf(("com_param_setup: Baud rate now %d\n", com_speed));
  680.  
  681. }
  682.  
  683.